/*
 * Copyright (C) 2012  Romain DUBOIS
 * 
 * This file is part of NeMoS - Network and Modular Software
 * 
 * NeMoS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * NeMoS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with NeMoS.  If not, see <http://www.gnu.org/licenses/>.
 */
package nemos.sample.greetings.swing;

import static nemos.sample.greetings.swing.SwingGreetingsMessage.CHANGE_LOCALE;
import static nemos.sample.greetings.swing.SwingGreetingsMessage.CHANGE_LOCALE_TEXT;
import static nemos.sample.greetings.swing.SwingGreetingsMessage.EXIT_LABEL;
import static nemos.sample.greetings.swing.SwingGreetingsMessage.GREETINGS;
import static nemos.sample.greetings.swing.SwingGreetingsMessage.GREET_LABEL;

import java.awt.event.ActionEvent;
import java.beans.EventHandler;
import java.util.Arrays;
import java.util.Collection;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JOptionPane;

import nemos.resources.IResourcesListener;
import nemos.resources.IResourcesManager;
import nemos.swing.IActionProvider;
import nemos.util.i18n.ITranslator;
import nemos.util.log.NemosLogger;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;

/**
 * SampleActions : The sample actions provider.
 * 
 * @author Romain DUBOIS
 */
@Service({ IActionProvider.class, IResourcesListener.class })
@Component(immediate = true)
public class SampleActions implements IActionProvider, IResourcesListener {

    /** The greetings action name */
    private static final String GREET_NAME = "sample.Greet"; //$NON-NLS-1$
    /** The exit action name */
    private static final String EXIT_NAME = "sample.Exit"; //$NON-NLS-1$
    /** The locale action name */
    private static final String LOCALE_NAME = "sample.Locale"; //$NON-NLS-1$

    /** The action names */
    private static final Collection<String> ACTION_NAMES = Arrays.asList(GREET_NAME, EXIT_NAME,
            LOCALE_NAME);

    /** The resources manager */
    @Reference(name = "resources")
    private IResourcesManager mResources;

    /** The greetings action */
    private AbstractAction mGreetAction;
    /** The exit action */
    private AbstractAction mExitAction;
    /** The locale action */
    private Action mLocaleAction;

    /** The bundle context */
    private BundleContext mContext;
    /** The logger */
    private NemosLogger mLogger;

    /** The available locales map */
    private final Map<String, Locale> mLocales;

    /**
     * Constructor.
     */
    public SampleActions() {
        super();
        mLocales = new TreeMap<String, Locale>();
    }

    /**
     * Start the component.
     * 
     * @param pContext
     *            The bundle context
     */
    @Activate
    public void start(final BundleContext pContext) {
        mContext = pContext;
        mLogger = new NemosLogger(SampleActions.class);

        mLocales.clear();
        for (final Locale lLocale : Locale.getAvailableLocales()) {
            if (lLocale.getCountry().isEmpty()) {
                mLocales.put(lLocale.getDisplayName(), lLocale);
            }
        }

        mGreetAction = new AbstractAction() {

            /** Serial version */
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(@SuppressWarnings("unused") final ActionEvent e) {
                setEnabled(false);
                new Thread(EventHandler.create(Runnable.class, SampleActions.this, "greet")) //$NON-NLS-1$
                        .start();
            }
        };

        mExitAction = new AbstractAction() {

            /** Serial version */
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(@SuppressWarnings("unused") final ActionEvent e) {
                new Thread(EventHandler.create(Runnable.class, SampleActions.this, "exit")).start(); //$NON-NLS-1$
            }
        };

        mLocaleAction = new AbstractAction() {

            /** Serial version */
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(@SuppressWarnings("unused") final ActionEvent pE) {

                new Thread(EventHandler.create(Runnable.class, SampleActions.this, "locale")).start(); //$NON-NLS-1$
            }
        };
    }

    /**
     * Stop the component.
     */
    @Deactivate
    protected void stop() {
        mGreetAction.setEnabled(false);
        mExitAction.setEnabled(false);
    }

    /**
     * {@inheritDoc}
     * 
     * @see nemos.swing.IActionProvider#getAction(java.lang.String)
     */
    @Override
    public Action getAction(final String pActionId) {
        if (GREET_NAME.equals(pActionId)) {
            return mGreetAction;
        }
        if (EXIT_NAME.equals(pActionId)) {
            return mExitAction;
        }
        if (LOCALE_NAME.equals(pActionId)) {
            return mLocaleAction;
        }
        return null;
    }

    /**
     * {@inheritDoc}
     * 
     * @see nemos.swing.IActionProvider#getAvailableActionIds()
     */
    @Override
    public Collection<String> getAvailableActionIds() {
        return ACTION_NAMES;
    }

    /**
     * Greet the user.
     */
    public void greet() {
        final String lUserName = System.getProperty("user.name"); //$NON-NLS-1$
        final String lText = mLogger.getTranslator().getLabel(GREETINGS, lUserName);
        JOptionPane.showMessageDialog(null, lText);
        mGreetAction.setEnabled(true);
    }

    /**
     * Exit the system.
     */
    public void exit() {
        try {
            mContext.getBundle(0).stop();
        } catch (final BundleException e) {
            mLogger.error(SwingGreetingsMessage.STOP_ERROR, e);
        }
    }

    /**
     * Change the user locale to french.
     */
    public void locale() {
        final String lTitle = mLogger.getTranslator().getLabel(CHANGE_LOCALE);
        final String lText = mLogger.getTranslator().getLabel(CHANGE_LOCALE_TEXT);

        final JOptionPane lOptionPane = new JOptionPane(lText, JOptionPane.PLAIN_MESSAGE,
                JOptionPane.OK_CANCEL_OPTION);
        lOptionPane.setLocale(mResources.getUserLocale());
        lOptionPane.setWantsInput(true);

        lOptionPane.setSelectionValues(mLocales.keySet().toArray());
        lOptionPane.setInitialSelectionValue(Locale.getDefault().getDisplayName());

        final JDialog lDialog = lOptionPane.createDialog(lTitle);
        // Blocking call
        lDialog.setVisible(true);

        if (lOptionPane.getInputValue() != JOptionPane.UNINITIALIZED_VALUE) {
            mResources.setUserLocale(mLocales.get(lOptionPane.getInputValue()));
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see nemos.resources.IResourcesListener#userLocaleChanged(java.util.Locale)
     */
    @Override
    public void userLocaleChanged(final Locale pLocale) {
        final ITranslator lTranslator = mLogger.getTranslator();
        mGreetAction.putValue(Action.NAME, lTranslator.getLabel(GREET_LABEL));
        mExitAction.putValue(Action.NAME, lTranslator.getLabel(EXIT_LABEL));
        if (pLocale == null) {
            mLocaleAction.putValue(Action.NAME, String.valueOf('-'));
            mLocaleAction.putValue(Action.LONG_DESCRIPTION, String.valueOf('?'));
        } else {
            mLocaleAction.putValue(Action.NAME, pLocale.toString());
            mLocaleAction.putValue(Action.SHORT_DESCRIPTION, pLocale.getDisplayName());
        }

        JComponent.setDefaultLocale(mResources.getUserLocale());
    }

    /**
     * {@inheritDoc}
     * 
     * @see nemos.resources.IResourcesListener#userResourcesChanged(java.lang.String)
     */
    @SuppressWarnings("unused")
    @Override
    public void userResourcesChanged(final String pResources) {
        // Nothing to do
    }

    /**
     * @param pResources
     *            the resources to set
     */
    public void bindResources(final IResourcesManager pResources) {
        mResources = pResources;
    }

    /**
     * @param pResources
     *            the resources to set
     */
    public void unbindResources(@SuppressWarnings("unused") final IResourcesManager pResources) {
        mResources = null;
    }
}
